//-----------------------------------------------------------------------------
//
// @file	Texture.h
// @brief	Texture include files, variables and classes
// @author	Vinod Melapudi
// @date	20Feb2010
//
//-----------------------------------------------------------------------------

#ifndef _TEXTURE_H
#define _TEXTURE_H

#include <vector>

#include "Color.h"
#include "Image.h"

class Texture
{
public:
	Texture();
	~Texture();
	void Bind() const;

	bool Load( const char* fileName, IMAGE_TYPE type );
	bool Load( const Image& image );

	uint	GetID() const		{ return m_gl_id; }
	uint	GetWidth() const	{ return m_width; }
	uint	GetHeight() const	{ return m_height; }

private:
	uint	m_gl_id;

	uint	m_width;
	uint	m_height;
	GLenum	m_color_mode;
};


// Generate gradient texture
template<class T>
bool GenerateGradientMapTexture( int tex_width, int tex_height, T* tex_data, GLenum color_mode,
								 const std::vector<Color<T>>& gradient_colors, const std::vector<int>& gradient_widths )
{
	assert( tex_data && tex_width > 1 && tex_height > 1 );
	assert( gradient_widths.size() == gradient_colors.size() - 1 );

	int num_components = color_mode == GL_RGB ? 3 : 4;

	// If one color specified, then fill that to all pixels
	if ( gradient_colors.size() == 1 )
	{
		int j = 0;
		for( int y = 0; y < tex_height; y++ )
			for( int x = 0; x < tex_width; x++ )
				for( int i = 0; i < num_components; i++ )
				{
					assert( j < tex_width * tex_height * num_components );
					tex_data[j++] = gradient_colors[0][i];
				}
		return true;
	}


	// Get total gradient widths
	int total_gradient_widths = 0;
	for( size_t i=0; i < gradient_widths.size(); i++ )
		total_gradient_widths += gradient_widths[i];


	// Remap gradient_widths
	std::vector<int> remapped_gradient_widths;
	remapped_gradient_widths.push_back( 0 );
	for( size_t i=0; i < gradient_widths.size(); i++ )
	{
		int height = (int)( (float)gradient_widths[i] * (float)tex_height / (float)total_gradient_widths );
		remapped_gradient_widths.push_back( height + remapped_gradient_widths.back() );
	}

	// Adjust last gradient height to tex_height
	remapped_gradient_widths[ remapped_gradient_widths.size()-1 ] = tex_height;


	assert( remapped_gradient_widths.size() == gradient_colors.size() );

	// Calculate gradient map for each section
	int j = 0;
	for( size_t g=0; g < remapped_gradient_widths.size()-1; g++ )
	{
		for( int y = remapped_gradient_widths[g]; y < remapped_gradient_widths[g+1]; y++ )
		{
			// Linear interpolate the color values values
			float lerp = (float)(y - remapped_gradient_widths[g]) / (float)(remapped_gradient_widths[g+1] - remapped_gradient_widths[g]);
			Color<T> color = gradient_colors[g].Lerp( gradient_colors[g+1], lerp );

			for( int x = 0; x < tex_width; x++ )
				for( int i = 0; i < num_components; i++ )
				{
					assert( j < tex_width * tex_height * num_components );
					tex_data[j++] = color[i];
				}
		}
	}

	return true;
}


#endif